package com.brainhealth.customer.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.math.MathUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.brainhealth.common.constant.ServiceExceptionStatus;
import com.brainhealth.common.enums.CustomerExerciseStatus;
import com.brainhealth.common.enums.PayStatus;
import com.brainhealth.common.enums.ReportType;
import com.brainhealth.common.enums.UpDownType;
import com.brainhealth.common.exception.ServiceException;
import com.brainhealth.common.utils.DateUtils;
import com.brainhealth.customer.domain.*;
import com.brainhealth.customer.domain.vo.CustomerCycleReportVO;
import com.brainhealth.customer.domain.vo.ExerciseTimeVO;
import com.brainhealth.customer.mapper.CustomerExerciseMapper;
import com.brainhealth.customer.mapper.CustomerScoreMapper;
import com.brainhealth.customer.mapper.ExerciseOrderMapper;
import com.brainhealth.utils.CommonUtils;
import org.apache.commons.math3.util.MathUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.brainhealth.customer.mapper.CustomerReportCycleMapper;
import com.brainhealth.customer.service.ICustomerReportCycleService;

import javax.servlet.http.HttpServletRequest;

/**
 * 会员阶段报告Service业务层处理
 * 
 * @author wolong
 * @date 2023-05-19
 */
@Service
public class CustomerReportCycleServiceImpl implements ICustomerReportCycleService 
{
    private static final Logger logger = LoggerFactory.getLogger(CustomerReportCycleServiceImpl.class);
    @Autowired
    private CustomerReportCycleMapper customerReportCycleMapper;
    @Autowired
    private CustomerExerciseMapper customerExerciseMapper;
    @Autowired
    private ExerciseOrderMapper exerciseOrderMapper;
    @Autowired
    private CustomerScoreMapper customerScoreMapper;


    /**
     * 查询会员阶段报告
     * 
     * @param customerReportCycleId 会员阶段报告主键
     * @return 会员阶段报告
     */
    @Override
    public CustomerReportCycle selectCustomerReportCycleByCustomerReportCycleId(Long customerReportCycleId)
    {
        return customerReportCycleMapper.selectCustomerReportCycleByCustomerReportCycleId(customerReportCycleId);
    }

    /**
     * 查询会员阶段报告列表
     * 
     * @param customerReportCycle 会员阶段报告
     * @return 会员阶段报告
     */
    @Override
    public List<CustomerReportCycle> selectCustomerReportCycleList(CustomerReportCycle customerReportCycle)
    {
        return customerReportCycleMapper.selectCustomerReportCycleList(customerReportCycle);
    }

    /**
     * 新增会员阶段报告
     * 
     * @param customerReportCycle 会员阶段报告
     * @return 结果
     */
    @Override
    public int insertCustomerReportCycle(CustomerReportCycle customerReportCycle)
    {
        customerReportCycle.setCreateTime(DateUtils.getNowDate());
        return customerReportCycleMapper.insertCustomerReportCycle(customerReportCycle);
    }

    /**
     * 修改会员阶段报告
     * 
     * @param customerReportCycle 会员阶段报告
     * @return 结果
     */
    @Override
    public int updateCustomerReportCycle(CustomerReportCycle customerReportCycle)
    {
        customerReportCycle.setUpdateTime(DateUtils.getNowDate());
        return customerReportCycleMapper.updateCustomerReportCycle(customerReportCycle);
    }

    /**
     * 批量删除会员阶段报告
     * 
     * @param customerReportCycleIds 需要删除的会员阶段报告主键
     * @return 结果
     */
    @Override
    public int deleteCustomerReportCycleByCustomerReportCycleIds(Long[] customerReportCycleIds)
    {
        return customerReportCycleMapper.deleteCustomerReportCycleByCustomerReportCycleIds(customerReportCycleIds);
    }

    /**
     * 删除会员阶段报告信息
     * 
     * @param customerReportCycleId 会员阶段报告主键
     * @return 结果
     */
    @Override
    public int deleteCustomerReportCycleByCustomerReportCycleId(Long customerReportCycleId)
    {
        return customerReportCycleMapper.deleteCustomerReportCycleByCustomerReportCycleId(customerReportCycleId);
    }

    @Override
    public CustomerCycleReportVO getCustomerReport(HttpServletRequest request)
    {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        if (customer.getMechanismId() != null && customer.getMechanismId().equals(-1L))
        {
            throw new ServiceException("体验用户无法查看报告，请付费！", ServiceExceptionStatus.EXPERIENCE_REPORT);
        }
        ExerciseOrder exerciseOrder = new ExerciseOrder();
        exerciseOrder.setCustomerId(customer.getCustomerId());
        List<ExerciseOrder> lstOrder = exerciseOrderMapper.selectExerciseOrderList(exerciseOrder);
        ExerciseOrder nowOrder = lstOrder.stream().filter(item -> item.getStatus() == PayStatus.Exercise).findFirst().orElse(null);
        if (nowOrder != null)
        {
            return getRealtimeReport(nowOrder, customer);
        }
        if (nowOrder == null)
        {
            List<ExerciseOrder> lstNowOrder = lstOrder.stream().filter(item -> item.getStatus() == PayStatus.Finish).collect(Collectors.toList());
            if (lstNowOrder.size() > 0)
            {
                nowOrder = lstNowOrder.get(lstNowOrder.size() - 1);
                return getRealtimeReport(nowOrder, customer);
            }
        }
        return null;
    }

    /**
     * 获取实时报告数据
     * @param order
     * @param customer
     * @return
     */
    public CustomerCycleReportVO getRealtimeReport(ExerciseOrder order, Customer customer)
    {
        CustomerExercise query = new CustomerExercise();
        query.setCustomerId(customer.getCustomerId());
        query.setOrderId(order.getOrderId());
        List<CustomerExercise> lstCustomerExercise = customerExerciseMapper.selectCustomerExerciseList(query);
        if (lstCustomerExercise.size() > 0)
        {
            CustomerScore queryScore = new CustomerScore();
            queryScore.setOrderId(order.getOrderId());
            queryScore.setCustomerId(customer.getCustomerId());
            List<CustomerScore> lstCustomerScore = customerScoreMapper.selectCustomerScoreList(queryScore);
            //获取当前订单中的周期时间
            int listSize = order.getCycle().intValue() / 7;
            List<List<CustomerScore>> lstScore = CommonUtils.getGroupList(listSize, lstCustomerScore);
            List<List<CustomerExercise>> lstExrecise = CommonUtils.getGroupList(listSize, lstCustomerExercise);
            CustomerCycleReportVO customerCycleReportVO = new CustomerCycleReportVO();
            customerCycleReportVO.setCustomerName(customer.getCustomerName());
            customerCycleReportVO.setSex(customer.getSex());
            customerCycleReportVO.setLevelIconUrl(customer.getCustomerLevel().getIcon());
            customerCycleReportVO.setLevelValue(customer.getLevelValue());
            customerCycleReportVO.setExerciseRemain(1);
            Map<Long, List<CustomerExercise>> mCustomerExercise = CommonUtils.getCountSortMap(lstCustomerExercise);
            for (Map.Entry<Long, List<CustomerExercise>> entry : mCustomerExercise.entrySet())
            {
                if (entry.getValue().get(0).getStatus() == CustomerExerciseStatus.NoOpen)
                {
                    customerCycleReportVO.setExerciseRemain(customerCycleReportVO.getExerciseRemain() + 1);
                }
                List<CustomerExercise> lstDayExercise = entry.getValue();
                CustomerExercise customerExercise = lstDayExercise.stream().filter(item -> item.getStatus() == CustomerExerciseStatus.NoFinish).findFirst().orElse(null);
                if (customerExercise == null)
                {
                    CustomerExercise tmpData = lstDayExercise.get(lstDayExercise.size() - 1);
                    if (tmpData.getStatus() != CustomerExerciseStatus.NoOpen)
                    {
                        if ((tmpData.getCountSort() % order.getCycle()) == 0)
                        {
                            customerCycleReportVO.setExerciseRemain(0);
                        }
                    }
                }
            }
            for (int i = 0; i < lstExrecise.size(); i++)
            {
                //获得当前阶段的所有训练记录
                List<CustomerExercise> lstItem = lstExrecise.get(i);
                CustomerExercise noFinish = lstItem.stream().filter(item -> item.getStatus() == CustomerExerciseStatus.NoFinish).findFirst().orElse(null);
                CustomerExercise allFinish = lstItem.get(lstItem.size() - 1);
                if (noFinish != null || (allFinish.getCountSort() % order.getCycle() == 0 && allFinish.getStatus() == CustomerExerciseStatus.Finished))
                {
                    customerCycleReportVO.setNowCycle(i + 1);
                    //对比上周的训练质量评分上升还是下降
                    int previousPos = i - 1;
                    int prePrevious = i - 2;
                    customerCycleReportVO.setPreviousCycleValue(0l);
                    customerCycleReportVO.setPreviousCycleUpDown(0l);
                    customerCycleReportVO.setPreviousValueType(UpDownType.KEEP);
                    if (previousPos >= 0)
                    {
                        for (CustomerScore score : lstScore.get(previousPos))
                        {
                            customerCycleReportVO.setPreviousCycleValue(customerCycleReportVO.getPreviousCycleValue() + score.getScore());
                        }
                    }
                    if (prePrevious >= 0)
                    {
                        Long prePreviousValue = 0l;
                        for (CustomerScore score : lstScore.get(prePrevious))
                        {
                            prePreviousValue += score.getScore();
                        }
                        Long difference = customerCycleReportVO.getPreviousCycleValue() - prePreviousValue;
                        customerCycleReportVO.setPreviousCycleUpDown(difference);
                        if (difference > 0)
                        {
                            customerCycleReportVO.setPreviousValueType(UpDownType.UP);
                        }
                        if (difference == 0)
                        {
                            customerCycleReportVO.setPreviousValueType(UpDownType.KEEP);
                        }
                        if (difference < 0)
                        {
                            customerCycleReportVO.setPreviousValueType(UpDownType.DOWN);
                        }
                    }
                    customerCycleReportVO.setNowCycleTime(0l);
                    customerCycleReportVO.setNowCycleCount(0);
                    customerCycleReportVO.setAttention(0l);
                    customerCycleReportVO.setExecute(0l);
                    customerCycleReportVO.setLogic(0l);
                    customerCycleReportVO.setMemory(0l);
                    if (customerCycleReportVO.getNowAttention() == null)
                    {
                        customerCycleReportVO.setNowAttention(0l);
                    }
                    if (customerCycleReportVO.getNowExecute() == null)
                    {
                        customerCycleReportVO.setNowExecute(0l);
                    }
                    if (customerCycleReportVO.getNowLogic() == null)
                    {
                        customerCycleReportVO.setNowLogic(0l);
                    }
                    if (customerCycleReportVO.getNowMemory() == null)
                    {
                        customerCycleReportVO.setNowMemory(0l);
                    }
                    Map<Long, List<CustomerExercise>> mExercise = new HashMap<>();
                    for (CustomerExercise item : lstItem)
                    {
                        if (item.getExerciseTime() != null)
                        {
                            customerCycleReportVO.setNowCycleTime(customerCycleReportVO.getNowCycleTime() + item.getExerciseTime());
                        }
                        if (item.getStatus() == CustomerExerciseStatus.Finished)
                        {
                            if (!mExercise.containsKey(item.getCountSort()))
                            {
                                mExercise.put(item.getCountSort(), new ArrayList<>());
                            }
                            mExercise.get(item.getCountSort()).add(item);
                            customerCycleReportVO.setNowCycleCount(customerCycleReportVO.getNowCycleCount() + 1);
                            customerCycleReportVO.setNowAttention(customerCycleReportVO.getNowAttention() + item.getAttention());
                            customerCycleReportVO.setNowExecute(customerCycleReportVO.getNowExecute() + item.getExecute());
                            customerCycleReportVO.setNowLogic(customerCycleReportVO.getNowLogic() + item.getLogic());
                            customerCycleReportVO.setNowMemory(customerCycleReportVO.getNowMemory() + item.getMemory());
                        }
                        customerCycleReportVO.setAttention(customerCycleReportVO.getAttention() + item.getAttention());
                        customerCycleReportVO.setExecute(customerCycleReportVO.getExecute() + item.getExecute());
                        customerCycleReportVO.setLogic(customerCycleReportVO.getLogic() + item.getLogic());
                        customerCycleReportVO.setMemory(customerCycleReportVO.getMemory() + item.getMemory());
                    }
                    ;
                    logger.info("当前用户的实时报告" + JSON.toJSONString(customerCycleReportVO));
                    //计算每次训练的总时长
                    for (Map.Entry<Long, List<CustomerExercise>> entry : mExercise.entrySet())
                    {
                        ExerciseTimeVO exerciseTimeVO = new ExerciseTimeVO();
                        exerciseTimeVO.setCountSort(entry.getKey());
                        Long exerciseTime = 0l;
                        for (CustomerExercise timeExercise : mExercise.get(entry.getKey()))
                        {
                            if (timeExercise.getExerciseTime() != null)
                            {
                                exerciseTime += timeExercise.getExerciseTime();
                            }
                        }
                        exerciseTimeVO.setTime(exerciseTime);
                        customerCycleReportVO.getLstExercise().add(exerciseTimeVO);
                    }
                    customerCycleReportVO.setNowCycleRemain(lstItem.size() - customerCycleReportVO.getNowCycleCount());
                    int percent = CommonUtils.getPercentValue(lstItem.size(), customerCycleReportVO.getNowCycleCount());
                    customerCycleReportVO.setNowCyclePercent(percent);
                    //对比前一个阶段的所有视频长度
                    Long previousTime = 0l;
                    int previousTimePos = i;
                    customerCycleReportVO.setPreviousTimeType(UpDownType.KEEP);
                    if ((previousTimePos - 1) >= 0)
                    {
                        for (CustomerExercise exercise : lstExrecise.get(previousTimePos - 1))
                        {
                            if (exercise.getExerciseTime() != null)
                            {
                                previousTime += exercise.getExerciseTime();
                            }
                        }
                        Long differenceTime = customerCycleReportVO.getNowCycleTime() - previousTime;
                        if (differenceTime > 0)
                        {
                            customerCycleReportVO.setPreviousTimeType(UpDownType.UP);
                        }
                        if (differenceTime == 0)
                        {
                            customerCycleReportVO.setPreviousTimeType(UpDownType.KEEP);
                        }
                        if (differenceTime < 0)
                        {
                            customerCycleReportVO.setPreviousTimeType(UpDownType.DOWN);
                        }
                        customerCycleReportVO.setPreviousCycleTime(differenceTime);
                        customerCycleReportVO.setExerciseDirection(RandomUtil.randomLong(1, 5));
                    }
                }
            }
            return customerCycleReportVO;
        }
        return null;
    }

    @Override
    public List<CustomerReportCycle> getCustomerReportTypeList(HttpServletRequest request, ReportType reportType)
    {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        CustomerReportCycle query = new CustomerReportCycle();
        query.setCustomerId(customer.getCustomerId());
        query.setReportType(reportType);
        List<CustomerReportCycle> lstReport = customerReportCycleMapper.selectCustomerReportCycleList(query);
        return lstReport;
    }
}
